package gm.server.virtual.simulator2D;

import com.sun.scenario.scenegraph.SGGroup;
import com.sun.scenario.scenegraph.SGShape;
import com.sun.scenario.scenegraph.SGTransform;
import gm.server.Tip;
import gm.server.WorkingArea;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

/**
 * Munkaterület komponens.
 *
 * @author imruf84
 */
public class WorkingAreaComponent extends WorkingArea {

    /**
     * Komponens.
     */
    private final SGGroup component = new SGGroup();
    /**
     * Első sarok síkidomja.
     */
    private final SGShape corner1Shape = new SGShape();
    /**
     * Második sarok síkidomja.
     */
    private final SGShape corner2Shape = new SGShape();
    /**
     * Első sarok transzformációja.
     */
    private final SGTransform.Affine corner1Transform = SGTransform.createAffine(null, null);
    /**
     * Második sarok transzformációja.
     */
    private final SGTransform.Affine corner2Transform = SGTransform.createAffine(null, null);
    /**
     * Keret.
     */
    private final SGShape edges = new SGShape();
    /**
     * Rács.
     */
    private final SGShape grid = new SGShape();

    /**
     * Konstruktor.
     *
     * @param tip
     */
    public WorkingAreaComponent(final Tip tip) {
        super(tip);

        double r = 1;

        // Első sarok.
        corner1Shape.setShape(new Rectangle2D.Double(-r, -r, 2 * r, 2 * r));
        corner1Shape.setFillPaint(new Color(1.0f, 0.0f, 1.0f, 0.6f));
        corner1Transform.setChild(corner1Shape);
        component.add(corner1Transform);

        // Második sarok.
        corner2Shape.setShape(new Rectangle2D.Double(-r, -r, 2 * r, 2 * r));
        corner2Shape.setFillPaint(new Color(1.0f, 0.0f, 1.0f, 0.6f));
        corner2Transform.setChild(corner2Shape);
        component.add(corner2Transform);

        // Rács.
        grid.setFillPaint(new Color(1.0f, 0.0f, 1.0f, 0.6f));
        grid.setAntialiasingHint(RenderingHints.VALUE_ANTIALIAS_ON);
        component.add(grid);

        // Keret.
        edges.setFillPaint(new Color(1.0f, 0.0f, 1.0f, 0.6f));
        edges.setAntialiasingHint(RenderingHints.VALUE_ANTIALIAS_ON);
        component.add(edges);

        updateTransform();
    }

    /**
     * Keret létrehozása.
     */
    private void updateFrame() {

        Point2D c[] = getBoundCorners(false);
        Point2D min = c[0];
        Point2D max = c[1];

        // Rács létrehozása.
        BasicStroke bsGrid = new BasicStroke(0.1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL, 0, null, 0);
        Path2D pathGrid = new Path2D.Double();
        for (long x = Math.round(min.getX()); x <= Math.round(max.getX()); x++) {
            pathGrid.moveTo(x, min.getY());
            pathGrid.lineTo(x, max.getY());
        }
        for (long y = Math.round(min.getY()); y <= Math.round(max.getY()); y++) {
            pathGrid.moveTo(min.getX(), y);
            pathGrid.lineTo(max.getX(), y);
        }
        grid.setShape(bsGrid.createStrokedShape(pathGrid));

        // Keret létrehozása.
        BasicStroke bsEdges = new BasicStroke(0.7f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL, 0, new float[]{1f, 1f}, 0);
        Path2D pathEdges = new Path2D.Double();
        pathEdges.moveTo(min.getX(), min.getY());
        pathEdges.lineTo(max.getX(), min.getY());
        pathEdges.lineTo(max.getX(), max.getY());
        pathEdges.lineTo(min.getX(), max.getY());
        pathEdges.closePath();
        edges.setShape(bsEdges.createStrokedShape(pathEdges));
    }

    /**
     * Transzformáció mátrixok frissítése.
     */
    private void updateTransform() {
        AffineTransform t1 = new AffineTransform();
        t1.setToIdentity();
        t1.translate(getCorner1(false).getX(), getCorner1(false).getY());
        corner1Transform.setAffine(t1);

        AffineTransform t2 = new AffineTransform();
        t2.setToIdentity();
        t2.translate(getCorner2(false).getX(), getCorner2(false).getY());
        corner2Transform.setAffine(t2);

        updateFrame();
    }

    /**
     * Komponens frissítése.
     */
    public void updateComponent() {
        updateTransform();
    }

    /**
     * Komponens lekérdezése.
     *
     * @return komponens
     */
    public SGGroup getComponent() {
        return component;
    }

    @Override
    public void storeCorner1ToCurrent() {
        super.storeCorner1ToCurrent();
        updateTransform();
    }

    @Override
    public void storeCorner2ToCurrent() {
        super.storeCorner2ToCurrent();
        updateTransform();
    }

}
